package com.hwapitest.testcase;
import com.alibaba.fastjson.JSONObject;
import com.hwapitest.entity.CaseData;
import com.hwapitest.entity.Variable;
import com.hwapitest.utils.*;
import org.apache.log4j.Logger;
import org.testng.annotations.*;
import org.testng.annotations.Optional;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import java.util.regex.Pattern;


public class BaseCase {
    public static Logger logger = Logger.getLogger(BaseCase.class);

    // 保存所有用例对象
    public static List<CaseData> cases = new ArrayList<CaseData>();

    // 存放变量对象的列表
    public static List<Variable> variables = new ArrayList<Variable>();

    String initSql;
    // 替换符
    public static Pattern replaceParamPattern = Pattern.compile("\\$\\{(.*?)\\}");

    // 存放全局变量的map
    public static Map<String, String> globalVariableMap = new HashMap<String, String>();

    public static Properties properties = new Properties();

    static {
        try {
            // 解决properties中中文乱码
            InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("src\\test\\resources\\config.properties"), "GBK");
            properties.load(inputStreamReader);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Parameters({ "excelPath", "dataSheetName", "variableSheetName"})
    @BeforeTest
    public void readDataFromExcel(
            @Optional("caseData/caseData.xlsx") String excelPath,
            @Optional("case") String dataSheetName,
            @Optional("variables") String variableSheetName) {

        logger.info("============= 开始加载测试表中数据 =============");
        logger.info("Excel路径: " + excelPath);
        logger.info("用例工作表: " + dataSheetName);
        logger.info("变量工作表: " + variableSheetName);

        // 加载测试用例
        try {
            cases = ExcelUtil.loadExcel(excelPath, dataSheetName, CaseData.class);
            logger.info("成功加载测试用例数量: " + cases.size());

            // 加载全局变量
            variables = ExcelUtil.loadExcel(excelPath, variableSheetName, Variable.class);
            logger.info("成功加载到variabres工作表的常量数量: " + variables.size());
            VariableUtil.loadVariablesToMap(variables);
            Set<String> keys = VariableUtil.variableMap.keySet();
            for (String key : keys) {
                logger.info("常量: " + key + " = " + VariableUtil.variableMap.get(key));
            }

        } catch (Exception e) {
            logger.error("加载Excel数据失败: " + e.getMessage(), e);
            throw new RuntimeException("测试数据初始化失败", e);
        }

        logger.info("============= 测试数据加载完成 =============\n");
        logger.info("读取文件获取到的cases对象：" + cases);
        logger.info("读取文件获取到的variables对象：" + variables);

    }
    @DataProvider(name = "datasFromExcel")
    public Iterator<Object[]> getCaseDatas(){
        List<Object[]> apiDataList = new ArrayList<Object[]>();
        for (CaseData caseData : cases){
            apiDataList.add(new Object[] { caseData });
        }
        return apiDataList.iterator();
    }
    @Test(dataProvider = "datasFromExcel", timeOut = 600000)
    public void test(CaseData caseData){
        // 获取对象中的数据
        String url = caseData.getUrl();
        String requestType = caseData.getRequestType();
        String headers = caseData.getHeaders();
        // String cookies = caseData.getCookies();  // 暂未涉及
        String parameters = caseData.getParameters();
        // String uploadFile = caseData.getUploadFile();  // 暂未涉及
        String initSql = caseData.getInitSql();
        String globalVariables = caseData.getGlobalVariables();
        String assertFields = caseData.getAssertFields();


        logger.info("url: " + url);
        logger.info("requestType: " + requestType);
        logger.info("headers: " + headers);
        logger.info("parameters: " + parameters);
        logger.info("initSql: " + initSql);
        logger.info("globalVariables: " + globalVariables);
        logger.info("assertFields: " + assertFields);

        logger.info("处理前的请求参数是："+parameters);
        // 替换入参中的非关联参数
        parameters = VariableUtil.variableSubstitution(parameters);
        // 替换入参中的关联参数
        parameters = GlobalVariableUtil.substitutionGlobalVariable(parameters);
        logger.info("处理后的请求参数是："+parameters);
        // 拼接url
        url = "http://" + properties.getProperty("project.ip").trim() + ":"+ properties.getProperty("project.port").trim() + url;
        logger.info(url);

        // 发送请求
        String actual = null;
        JSONObject headsJsonObject = null;

        try {
            // 安全解析请求头
            headsJsonObject = JSONObject.parseObject(headers);
        } catch (Exception e) {
            // 仅添加错误日志，不改变原有逻辑
            logger.error("请求头解析失败，请检查格式: " + headers);
            throw new RuntimeException("请求头格式错误，必须是有效的JSON格式");
        }

        // 根据请求头判断是发送json还是非json
        try {
            if (headsJsonObject != null && "application/json".equals(headsJsonObject.getString("Content-Type"))) {
                // 解析json格式字符串为JSONObject
                JSONObject paramJsonObject = null;

                try {
                    paramJsonObject = JSONObject.parseObject(parameters);
                } catch (Exception e) {
                    // 添加详细错误日志，不改变原有逻辑
                    logger.error("JSON参数解析失败! 原始参数: " + parameters);
                    logger.error("JSON解析错误: " + e.getMessage());
                    throw new RuntimeException("参数格式错误，必须是有效的JSON格式");
                }

                // 请求
                actual = HttpRequestJsonUtil.sendRequest(url, requestType, paramJsonObject, headsJsonObject);
                logger.info("json请求返回结果： " + actual);
            } else {
                HashMap<String, String> params = new HashMap<String, String>();
                // 解析json格式字符串为JSONObject
                JSONObject jsonObject = null;

                try {
                    jsonObject = JSONObject.parseObject(parameters);
                } catch (Exception e) {
                    // 添加详细错误日志，不改变原有逻辑
                    logger.error("表单参数解析失败! 原始参数: " + parameters);
                    logger.error("JSON解析错误: " + e.getMessage());
                    throw new RuntimeException("参数格式错误，必须是有效的JSON格式");
                }

                // JSONObject转换为map
                Set<String> keys = jsonObject.keySet();
                for (String key : keys) {
                    params.put(key, jsonObject.getString(key));
                }
                // 请求，获取结果
                actual = HttpRequestUtil.sendRequest(url, requestType, params);
                logger.info("k-v请求返回结果： " + actual);
            }
        } catch (Exception e) {
            // 添加完整的错误上下文信息
            logger.error("请求处理失败! URL: " + url);
            logger.error("请求类型: " + requestType);
            logger.error("请求头: " + headers);
            logger.error("参数: " + parameters);
            throw e;
        }
        // 是否需要保存全局变量
        if (StringUtil.isNotNullAndEmpty(globalVariables)){
            logger.info("开始保存全局变量：" + globalVariables);
            GlobalVariableUtil.saveGlobalVariable(actual, globalVariables);
        }
        // 是否需要断言关键字段
        if (StringUtil.isNotNullAndEmpty(assertFields)){
            AssertUtil.getFieldsAssertRes(actual, assertFields);
        }

        // 执行初始化sql,需要时开启
//        if (initSql!=null && initSql.trim().length()>0){
//            // 替换sql中的参数
//            initSql = VariableUtil.variableSubstitution(initSql);
//
//            // 调用方法
//            InitSqlUtil.doInitSql(initSql);
//        }
    }
}
